home *** CD-ROM | disk | FTP | other *** search
- Subject: v22i097: GNU AWK, version 2.11, Part11/16
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: e4e7be9b 6cd97e54 9e8ebd46 c352a92b
-
- Submitted-by: "Arnold D. Robbins" <arnold@unix.cc.emory.edu>
- Posting-number: Volume 22, Issue 97
- Archive-name: gawk2.11/part11
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: ./gawk.1 ./io.c ./missing.d/memcpy.c
- # Wrapped by rsalz@litchi.bbn.com on Wed Jun 6 12:24:56 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 11 (of 16)."'
- if test -f './gawk.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./gawk.1'\"
- else
- echo shar: Extracting \"'./gawk.1'\" \(33549 characters\)
- sed "s/^X//" >'./gawk.1' <<'END_OF_FILE'
- X.TH GAWK 1 "August 24 1989" "Free Software Foundation"
- X.SH NAME
- Xgawk \- pattern scanning and processing language
- X.SH SYNOPSIS
- X.B gawk
- X.ig
- X[
- X.B \-d
- X] [
- X.B \-D
- X]
- X..
- X[
- X.B \-a
- X] [
- X.B \-e
- X] [
- X.B \-c
- X] [
- X.B \-C
- X] [
- X.B \-V
- X] [
- X.BI \-F\^ fs
- X] [
- X.B \-v
- X.IR var = val
- X]
- X.B \-f
- X.I program-file
- X[
- X.B \-\^\-
- X] file .\^.\^.
- X.br
- X.B gawk
- X.ig
- X[
- X.B \-d
- X] [
- X.B \-D
- X]
- X..
- X[
- X.B \-a
- X] [
- X.B \-e
- X] [
- X.B \-c
- X] [
- X.B \-C
- X] [
- X.B \-V
- X] [
- X.BI \-F\^ fs
- X] [
- X.B \-v
- X.IR var = val
- X] [
- X.B \-\^\-
- X]
- X.I program-text
- Xfile .\^.\^.
- X.SH DESCRIPTION
- X.I Gawk
- Xis the GNU Project's implementation of the AWK programming language.
- XIt conforms to the definition and description of the language in
- X.IR "The AWK Programming Language" ,
- Xby Aho, Kernighan, and Weinberger,
- Xwith the additional features defined in the System V Release 4 version
- Xof \s-1UNIX\s+1
- X.IR awk ,
- Xand some GNU-specific extensions.
- X.PP
- XThe command line consists of options to
- X.I gawk
- Xitself, the AWK program text (if not supplied via the
- X.B \-f
- Xoption), and values to be made
- Xavailable in the
- X.B ARGC
- Xand
- X.B ARGV
- Xpre-defined AWK variables.
- X.PP
- X.I Gawk
- Xaccepts the following options, which should be available on any implementation
- Xof the AWK language.
- X.TP
- X.BI \-F fs
- XUse
- X.I fs
- Xfor the input field separator (the value of the
- X.B FS
- Xpredefined
- Xvariable).
- X.TP
- X\fB\-v\fI var\fR\^=\^\fIval\fR
- XAssign the value
- X.IR val ,
- Xto the variable
- X.IR var ,
- Xbefore execution of the program begins.
- XSuch variable values are available to the
- X.B BEGIN
- Xblock of an AWK program.
- X.TP
- X.BI \-f " program-file"
- XRead the AWK program source from the file
- X.IR program-file ,
- Xinstead of from the first command line argument.
- XMultiple
- X.B \-f
- Xoptions may be used.
- X.TP
- X.B \-\^\-
- XSignal the end of options. This is useful to allow further arguments to the
- XAWK program itself to start with a ``\-''.
- XThis is mainly for consistency with the argument parsing convention used
- Xby most other System V programs.
- X.PP
- XThe following options are specific to the GNU implementation.
- X.TP
- X.B \-a
- XUse AWK style regular expressions as described in the book.
- XThis is the current default, but may not be when the POSIX P1003.2
- Xstandard is finalized.
- XIt is orthogonal to
- X.BR \-c .
- X.TP
- X.B \-e
- XUse
- X.IR egrep (1)
- Xstyle regular expressions as described in POSIX standard.
- XThis may become the default when the POSIX P1003.2
- Xstandard is finalized.
- XIt is orthogonal to
- X.BR \-c .
- X.TP
- X.B \-c
- XRun in
- X.I compatibility
- Xmode. In compatibility mode,
- X.I gawk
- Xbehaves identically to \s-1UNIX\s+1
- X.IR awk ;
- Xnone of the GNU-specific extensions are recognized.
- X.TP
- X.B \-C
- XPrint the short version of the GNU copyright information message on
- Xthe error output.
- XThis option may disappear in a future version of
- X.IR gawk .
- X.TP
- X.B \-V
- XPrint version information for this particular copy of
- X.I gawk
- Xon the error output.
- XThis is useful mainly for knowing if the current copy of
- X.I gawk
- Xon your system
- Xis up to date with respect to whatever the Free Software Foundation
- Xis distributing.
- XThis option may disappear in a future version of
- X.IR gawk .
- X.PP
- XAny other options are flagged as illegal, but are otherwise ignored.
- X.PP
- XAn AWK program consists of a sequence of pattern-action statements
- Xand optional function definitions.
- X.RS
- X.PP
- X\fIpattern\fB { \fIaction statements\fB }\fR
- X.br
- X\fBfunction \fIname\fB(\fIparameter list\fB) { \fIstatements\fB }\fR
- X.RE
- X.PP
- X.I Gawk
- Xfirst reads the program source from the
- X.IR program-file (s)
- Xif specified, or from the first non-option argument on the command line.
- XThe
- X.B \-f
- Xoption may be used multiple times on the command line.
- X.I Gawk
- Xwill read the program text as if all the
- X.IR program-file s
- Xhad been concatenated together. This is useful for building libraries
- Xof AWK functions, without having to include them in each new AWK
- Xprogram that uses them. To use a library function in a file from a
- Xprogram typed in on the command line, specify
- X.B /dev/tty
- Xas one of the
- X.IR program-file s,
- Xtype your program, and end it with a
- X.B ^D
- X(control-d).
- X.PP
- XThe environment variable
- X.B AWKPATH
- Xspecifies a search path to use when finding source files named with
- Xthe
- X.B \-f
- Xoption. If this variable does not exist, the default path is
- X\fB".:/usr/lib/awk:/usr/local/lib/awk"\fR.
- XIf a file name given to the
- X.B \-f
- Xoption contains a ``/'' character, no path search is performed.
- X.PP
- X.I Gawk
- Xcompiles the program into an internal form,
- Xexecutes the code in the
- X.B BEGIN
- Xblock(s) (if any),
- Xand then proceeds to read
- Xeach file named in the
- X.B ARGV
- Xarray.
- XIf there are no files named on the command line,
- X.I gawk
- Xreads the standard input.
- X.PP
- XIf a ``file'' named on the command line has the form
- X.IB var = val
- Xit is treated as a variable assignment. The variable
- X.I var
- Xwill be assigned the value
- X.IR val .
- XThis is most useful for dynamically assigning values to the variables
- XAWK uses to control how input is broken into fields and records. It
- Xis also useful for controlling state if multiple passes are needed over
- Xa single data file.
- X.PP
- XFor each line in the input,
- X.I gawk
- Xtests to see if it matches any
- X.I pattern
- Xin the AWK program.
- XFor each pattern that the line matches, the associated
- X.I action
- Xis executed.
- X.SH VARIABLES AND FIELDS
- XAWK variables are dynamic; they come into existence when they are
- Xfirst used. Their values are either floating-point numbers or strings,
- Xdepending upon how they are used. AWK also has one dimension
- Xarrays; multiply dimensioned arrays may be simulated.
- XThere are several pre-defined variables that AWK sets as a program
- Xruns; these will be described as needed and summarized below.
- X.SS Fields
- X.PP
- XAs each input line is read,
- X.I gawk
- Xsplits the line into
- X.IR fields ,
- Xusing the value of the
- X.B FS
- Xvariable as the field separator.
- XIf
- X.B FS
- Xis a single character, fields are separated by that character.
- XOtherwise,
- X.B FS
- Xis expected to be a full regular expression.
- XIn the special case that
- X.B FS
- Xis a single blank, fields are separated
- Xby runs of blanks and/or tabs.
- XNote that the value of
- X.B IGNORECASE
- X(see below) will also affect how fields are split when
- X.B FS
- Xis a regular expression.
- X.PP
- XEach field in the input line may be referenced by its position,
- X.BR $1 ,
- X.BR $2 ,
- Xand so on.
- X.B $0
- Xis the whole line. The value of a field may be assigned to as well.
- XFields need not be referenced by constants:
- X.RS
- X.PP
- X.ft B
- Xn = 5
- X.br
- Xprint $n
- X.ft R
- X.RE
- X.PP
- Xprints the fifth field in the input line.
- XThe variable
- X.B NF
- Xis set to the total number of fields in the input line.
- X.PP
- XReferences to non-existent fields (i.e. fields after
- X.BR $NF ),
- Xproduce the null-string. However, assigning to a non-existent field
- X(e.g.,
- X.BR "$(NF+2) = 5" )
- Xwill increase the value of
- X.BR NF ,
- Xcreate any intervening fields with the null string as their value, and
- Xcause the value of
- X.B $0
- Xto be recomputed, with the fields being separated by the value of
- X.BR OFS .
- X.SS Built-in Variables
- X.PP
- XAWK's built-in variables are:
- X.PP
- X.RS
- X.TP \l'\fBIGNORECASE\fR'
- X.B ARGC
- Xthe number of command line arguments (does not include options to
- X.IR gawk ,
- Xor the program source).
- X.TP \l'\fBIGNORECASE\fR'
- X.B ARGV
- Xarray of command line arguments. The array is indexed from
- X0 to
- X.B ARGC
- X\- 1.
- XDynamically changing the contents of
- X.B ARGV
- Xcan control the files used for data.
- X.TP \l'\fBIGNORECASE\fR'
- X.B ENVIRON
- XAn array containing the values of the current environment.
- XThe array is indexed by the environment variables, each element being
- Xthe value of that variable (e.g., \fBENVIRON["HOME"]\fP might be
- X.BR /u/arnold ).
- XChanging this array does not affect the environment seen by programs which
- X.I gawk
- Xspawns via redirection or the
- X.B system
- Xfunction.
- X(This may change in a future version of
- X.IR gawk .)
- X.TP \l'\fBIGNORECASE\fR'
- X.B FILENAME
- Xthe name of the current input file.
- XIf no files are specified on the command line, the value of
- X.B FILENAME
- Xis ``\-''.
- X.TP \l'\fBIGNORECASE\fR'
- X.B FNR
- Xthe input record number in the current input file.
- X.TP \l'\fBIGNORECASE\fR'
- X.B FS
- Xthe input field separator, a blank by default.
- X.TP \l'\fBIGNORECASE\fR'
- X.B IGNORECASE
- XControls the case-sensitivity of all regular expression operations. If
- X.B IGNORECASE
- Xhas a non-zero value, then pattern matching in rules,
- Xfield splitting with
- X.BR FS ,
- Xregular expression
- Xmatching with
- X.B ~
- Xand
- X.BR !~ ,
- Xand the
- X.BR gsub() ,
- X.BR index() ,
- X.BR match() ,
- X.BR split() ,
- Xand
- X.B sub()
- Xpre-defined functions will all ignore case when doing regular expression
- Xoperations. Thus, if
- X.B IGNORECASE
- Xis not equal to zero,
- X.B /aB/
- Xmatches all of the strings \fB"ab"\fP, \fB"aB"\fP, \fB"Ab"\fP,
- Xand \fB"AB"\fP.
- XAs with all AWK variables, the initial value of
- X.B IGNORECASE
- Xis zero, so all regular expression operations are normally case-sensitive.
- X.TP \l'\fBIGNORECASE\fR'
- X.B NF
- Xthe number of fields in the current input record.
- X.TP \l'\fBIGNORECASE\fR'
- X.B NR
- Xthe total number of input records seen so far.
- X.TP \l'\fBIGNORECASE\fR'
- X.B OFMT
- Xthe output format for numbers,
- X.B %.6g
- Xby default.
- X.TP \l'\fBIGNORECASE\fR'
- X.B OFS
- Xthe output field separator, a blank by default.
- X.TP \l'\fBIGNORECASE\fR'
- X.B ORS
- Xthe output record separator, by default a newline.
- X.TP \l'\fBIGNORECASE\fR'
- X.B RS
- Xthe input record separator, by default a newline.
- X.B RS
- Xis exceptional in that only the first character of its string
- Xvalue is used for separating records. If
- X.B RS
- Xis set to the null string, then records are separated by
- Xblank lines.
- XWhen
- X.B RS
- Xis set to the null string, then the newline character always acts as
- Xa field separator, in addition to whatever value
- X.B FS
- Xmay have.
- X.TP \l'\fBIGNORECASE\fR'
- X.B RSTART
- Xthe index of the first character matched by
- X.BR match() ;
- X0 if no match.
- X.TP \l'\fBIGNORECASE\fR'
- X.B RLENGTH
- Xthe length of the string matched by
- X.BR match() ;
- X\-1 if no match.
- X.TP \l'\fBIGNORECASE\fR'
- X.B SUBSEP
- Xthe character used to separate multiple subscripts in array
- Xelements, by default \fB"\e034"\fR.
- X.RE
- X.SS Arrays
- X.PP
- XArrays are subscripted with an expression between square brackets
- X.RB ( [ " and " ] ).
- XIf the expression is an expression list
- X.RI ( expr ", " expr " ...)"
- Xthen the array subscript is a string consisting of the
- Xconcatenation of the (string) value of each expression,
- Xseparated by the value of the
- X.B SUBSEP
- Xvariable.
- XThis facility is used to simulate multiply dimensioned
- Xarrays. For example:
- X.PP
- X.RS
- X.ft B
- Xi = "A" ;\^ j = "B" ;\^ k = "C"
- X.br
- Xx[i, j, k] = "hello, world\en"
- X.ft R
- X.RE
- X.PP
- Xassigns the string \fB"hello, world\en"\fR to the element of the array
- X.B x
- Xwhich is indexed by the string \fB"A\e034B\e034C"\fR. All arrays in AWK
- Xare associative, i.e. indexed by string values.
- X.PP
- XThe special operator
- X.B in
- Xmay be used in an
- X.B if
- Xor
- X.B while
- Xstatement to see if an array has an index consisting of a particular
- Xvalue.
- X.PP
- X.RS
- X.ft B
- X.nf
- Xif (val in array)
- X print array[val]
- X.fi
- X.ft
- X.RE
- X.PP
- XIf the array has multiple subscripts, use
- X.BR "(i, j) in array" .
- X.PP
- XThe
- X.B in
- Xconstruct may also be used in a
- X.B for
- Xloop to iterate over all the elements of an array.
- X.PP
- XAn element may be deleted from an array using the
- X.B delete
- Xstatement.
- X.SS Variable Typing
- X.PP
- XVariables and fields
- Xmay be (floating point) numbers, or strings, or both. How the
- Xvalue of a variable is interpreted depends upon its context. If used in
- Xa numeric expression, it will be treated as a number, if used as a string
- Xit will be treated as a string.
- X.PP
- XTo force a variable to be treated as a number, add 0 to it; to force it
- Xto be treated as a string, concatenate it with the null string.
- X.PP
- XThe AWK language defines comparisons as being done numerically if
- Xpossible, otherwise one or both operands are converted to strings and
- Xa string comparison is performed.
- X.PP
- XUninitialized variables have the numeric value 0 and the string value ""
- X(the null, or empty, string).
- X.SH PATTERNS AND ACTIONS
- XAWK is a line oriented language. The pattern comes first, and then the
- Xaction. Action statements are enclosed in
- X.B {
- Xand
- X.BR } .
- XEither the pattern may be missing, or the action may be missing, but,
- Xof course, not both. If the pattern is missing, the action will be
- Xexecuted for every single line of input.
- XA missing action is equivalent to
- X.RS
- X.PP
- X.B "{ print }"
- X.RE
- X.PP
- Xwhich prints the entire line.
- X.PP
- XComments begin with the ``#'' character, and continue until the
- Xend of the line.
- XBlank lines may be used to separate statements.
- XNormally, a statement ends with a newline, however, this is not the
- Xcase for lines ending in
- Xa ``,'', ``{'', ``?'', ``:'', ``&&'', or ``||''.
- XLines ending in
- X.B do
- Xor
- X.B else
- Xalso have their statements automatically continued on the following line.
- XIn other cases, a line can be continued by ending it with a ``\e'',
- Xin which case the newline will be ignored.
- X.PP
- XMultiple statements may
- Xbe put on one line by separating them with a ``;''.
- XThis applies to both the statements within the action part of a
- Xpattern-action pair (the usual case),
- Xand to the pattern-action statements themselves.
- X.SS Patterns
- XAWK patterns may be one of the following:
- X.PP
- X.RS
- X.nf
- X.B BEGIN
- X.B END
- X.BI / "regular expression" /
- X.I "relational expression"
- X.IB pattern " && " pattern
- X.IB pattern " || " pattern
- X.IB pattern " ? " pattern " : " pattern
- X.BI ( pattern )
- X.BI ! " pattern"
- X.IB pattern1 ", " pattern2"
- X.fi
- X.RE
- X.PP
- X.B BEGIN
- Xand
- X.B END
- Xare two special kinds of patterns which are not tested against
- Xthe input.
- XThe action parts of all
- X.B BEGIN
- Xpatterns are merged as if all the statements had
- Xbeen written in a single
- X.B BEGIN
- Xblock. They are executed before any
- Xof the input is read. Similarly, all the
- X.B END
- Xblocks are merged,
- Xand executed when all the input is exhausted (or when an
- X.B exit
- Xstatement is executed).
- X.B BEGIN
- Xand
- X.B END
- Xpatterns cannot be combined with other patterns in pattern expressions.
- X.B BEGIN
- Xand
- X.B END
- Xpatterns cannot have missing action parts.
- X.PP
- XFor
- X.BI / "regular expression" /
- Xpatterns, the associated statement is executed for each input line that matches
- Xthe regular expression.
- XRegular expressions are the same as those in
- X.IR egrep (1),
- Xand are summarized below.
- X.PP
- XA
- X.I "relational expression"
- Xmay use any of the operators defined below in the section on actions.
- XThese generally test whether certain fields match certain regular expressions.
- X.PP
- XThe
- X.BR && ,
- X.BR || ,
- Xand
- X.B !
- Xoperators are logical AND, logical OR, and logical NOT, respectively, as in C.
- XThey do short-circuit evaluation, also as in C, and are used for combining
- Xmore primitive pattern expressions. As in most languages, parentheses
- Xmay be used to change the order of evaluation.
- X.PP
- XThe
- X.B ?\^:
- Xoperator is like the same operator in C. If the first pattern is true
- Xthen the pattern used for testing is the second pattern, otherwise it is
- Xthe third. Only one of the second and third patterns is evaluated.
- X.PP
- XThe
- X.IB pattern1 ", " pattern2"
- Xform of an expression is called a range pattern.
- XIt matches all input lines starting with a line that matches
- X.IR pattern1 ,
- Xand continuing until a line that matches
- X.IR pattern2 ,
- Xinclusive. It does not combine with any other sort of pattern expression.
- X.SS Regular Expressions
- XRegular expressions are the extended kind found in
- X.IR egrep .
- XThey are composed of characters as follows:
- X.RS
- X.TP \l'[^abc...]'
- X.I c
- Xmatches the non-metacharacter
- X.IR c .
- X.TP \l'[^abc...]'
- X.I \ec
- Xmatches the literal character
- X.IR c .
- X.TP \l'[^abc...]'
- X.B .
- Xmatches any character except newline.
- X.TP \l'[^abc...]'
- X.B ^
- Xmatches the beginning of a line or a string.
- X.TP \l'[^abc...]'
- X.B $
- Xmatches the end of a line or a string.
- X.TP \l'[^abc...]'
- X.BI [ abc... ]
- Xcharacter class, matches any of the characters
- X.IR abc... .
- X.TP \l'[^abc...]'
- X.BI [^ abc... ]
- Xnegated character class, matches any character except
- X.I abc...
- Xand newline.
- X.TP \l'[^abc...]'
- X.IB r1 | r2
- Xalternation: matches either
- X.I r1
- Xor
- X.IR r2 .
- X.TP \l'[^abc...]'
- X.I r1r2
- Xconcatenation: matches
- X.IR r1 ,
- Xand then
- X.IR r2 .
- X.TP \l'[^abc...]'
- X.IB r +
- Xmatches one or more
- X.IR r 's.
- X.TP \l'[^abc...]'
- X.IB r *
- Xmatches zero or more
- X.IR r 's.
- X.TP \l'[^abc...]'
- X.IB r ?
- Xmatches zero or one
- X.IR r 's.
- X.TP \l'[^abc...]'
- X.BI ( r )
- Xgrouping: matches
- X.IR r .
- X.RE
- XThe escape sequences that are valid in string constants (see below)
- Xare also legal in regular expressions.
- X.SS Actions
- XAction statements are enclosed in braces,
- X.B {
- Xand
- X.BR } .
- XAction statements consist of the usual assignment, conditional, and looping
- Xstatements found in most languages. The operators, control statements,
- Xand input/output statements
- Xavailable are patterned after those in C.
- X.SS Operators
- X.PP
- XThe operators in AWK, in order of increasing precedence, are
- X.PP
- X.RS
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B "= += \-= *= /= %= ^="
- XAssignment. Both absolute assignment
- X.BI ( var " = " value )
- Xand operator-assignment (the other forms) are supported.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B ?:
- XThe C conditional expression. This has the form
- X.IB expr1 " ? " expr2 " : " expr3\c
- X\&. If
- X.I expr1
- Xis true, the value of the expression is
- X.IR expr2 ,
- Xotherwise it is
- X.IR expr3 .
- XOnly one of
- X.I expr2
- Xand
- X.I expr3
- Xis evaluated.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B ||
- Xlogical OR.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B &&
- Xlogical AND.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B "~ !~"
- Xregular expression match, negated match.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B "< <= > >= != =="
- Xthe regular relational operators.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.I blank
- Xstring concatenation.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B "+ \-"
- Xaddition and subtraction.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B "* / %"
- Xmultiplication, division, and modulus.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B "+ \- !"
- Xunary plus, unary minus, and logical negation.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B ^
- Xexponentiation (\fB**\fR may also be used, and \fB**=\fR for
- Xthe assignment operator).
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B "++ \-\^\-"
- Xincrement and decrement, both prefix and postfix.
- X.TP \l'\fB= += \-= *= /= %= ^=\fR'
- X.B $
- Xfield reference.
- X.RE
- X.SS Control Statements
- X.PP
- XThe control statements are
- Xas follows:
- X.PP
- X.RS
- X.nf
- X\fBif (\fIcondition\fB) \fIstatement\fR [ \fBelse\fI statement \fR]
- X\fBwhile (\fIcondition\fB) \fIstatement \fR
- X\fBdo \fIstatement \fBwhile (\fIcondition\fB)\fR
- X\fBfor (\fIexpr1\fB; \fIexpr2\fB; \fIexpr3\fB) \fIstatement\fR
- X\fBfor (\fIvar \fBin\fI array\fB) \fIstatement\fR
- X\fBbreak\fR
- X\fBcontinue\fR
- X\fBdelete \fIarray\^\fB[\^\fIindex\^\fB]\fR
- X\fBexit\fR [ \fIexpression\fR ]
- X\fB{ \fIstatements \fB}
- X.fi
- X.RE
- X.SS "I/O Statements"
- X.PP
- XThe input/output statements are as follows:
- X.PP
- X.RS
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI close( filename )
- Xclose file (or pipe, see below).
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.B getline
- Xset
- X.B $0
- Xfrom next input record; set
- X.BR NF ,
- X.BR NR ,
- X.BR FNR .
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI "getline <" file
- Xset
- X.B $0
- Xfrom next record of
- X.IR file ;
- Xset
- X.BR NF .
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI getline " var"
- Xset
- X.I var
- Xfrom next input record; set
- X.BR NF ,
- X.BR FNR .
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI getline " var" " <" file
- Xset
- X.I var
- Xfrom next record of
- X.IR file .
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.B next
- XStop processing the current input record. The next input record
- Xis read and processing starts over with the first pattern in the
- XAWK program. If the end of the input data is reached, the
- X.B END
- Xblock(s), if any, are executed.
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.B print
- Xprints the current record.
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI print " expr-list"
- Xprints expressions.
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI print " expr-list" " >" file
- Xprints expressions on
- X.IR file .
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI printf " fmt, expr-list"
- Xformat and print.
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI printf " fmt, expr-list" " >" file
- Xformat and print on
- X.IR file .
- X.TP \l'\fBprintf \fIfmt, expr-list\fR'
- X.BI system( cmd-line )
- Xexecute the command
- X.IR cmd-line ,
- Xand return the exit status.
- X(This may not be available on
- Xsystems besides \s-1UNIX\s+1 and \s-1GNU\s+1.)
- X.RE
- X.PP
- XOther input/output redirections are also allowed. For
- X.B print
- Xand
- X.BR printf ,
- X.BI >> file
- Xappends output to the
- X.IR file ,
- Xwhile
- X.BI | " command"
- Xwrites on a pipe.
- XIn a similar fashion,
- X.IB command " | getline"
- Xpipes into
- X.BR getline .
- X.BR Getline
- Xwill return 0 on end of file, and \-1 on an error.
- X.SS The \fIprintf\fP Statement
- X.PP
- XThe AWK versions of the
- X.B printf
- Xand
- X.B sprintf
- X(see below)
- Xfunctions accept the following conversion specification formats:
- X.RS
- X.TP
- X.B %c
- XAn ASCII character.
- XIf the argument used for
- X.B %c
- Xis numeric, it is treated as a character and printed.
- XOtherwise, the argument is assumed to be a string, and the only first
- Xcharacter of that string is printed.
- X.TP
- X.B %d
- XA decimal number (the integer part).
- X.TP
- X.B %i
- XJust like
- X.BR %d .
- X.TP
- X.B %e
- XA floating point number of the form
- X.BR [\-]d.ddddddE[+\^\-]dd .
- X.TP
- X.B %f
- XA floating point number of the form
- X.BR [\-]ddd.dddddd .
- X.TP
- X.B %g
- XUse
- X.B e
- Xor
- X.B f
- Xconversion, whichever is shorter, with nonsignificant zeros suppressed.
- X.TP
- X.B %o
- XAn unsigned octal number (again, an integer).
- X.TP
- X.B %s
- XA character string.
- X.TP
- X.B %x
- XAn unsigned hexadecimal number (an integer).
- X.TP
- X.B %X
- XLike
- X.BR %x ,
- Xbut using
- X.B ABCDEF
- Xinstead of
- X.BR abcdef .
- X.TP
- X.B %%
- XA single
- X.B %
- Xcharacter; no argument is converted.
- X.RE
- X.PP
- XThere are optional, additional parameters that may lie between the
- X.B %
- Xand the control letter:
- X.RS
- X.TP
- X.B \-
- XThe expression should be left-justified within its field.
- X.TP
- X.I width
- XThe field should be padded to this width. If the number has a leading
- Xzero, then the field will be padded with zeros.
- XOtherwise it is padded with blanks.
- X.TP
- X.BI . prec
- XA number indicating the maximum width of strings or digits to the right
- Xof the decimal point.
- X.RE
- X.PP
- XThe dynamic
- X.I width
- Xand
- X.I prec
- Xcapabilities of the C library
- X.B printf
- Xroutines are not supported.
- XHowever, they may be simulated by using
- Xthe AWK concatenation operation to build up
- Xa format specification dynamically.
- X.SS Special File Names
- X.PP
- XWhen doing I/O redirection from either
- X.B print
- Xor
- X.B printf
- Xinto a file,
- Xor via
- X.B getline
- Xfrom a file,
- X.I gawk
- Xrecognizes certain special filenames internally. These filenames
- Xallow access to open file descriptors inherited from
- X.IR gawk 's
- Xparent process (usually the shell). The filenames are:
- X.RS
- X.TP
- X.B /dev/stdin
- XThe standard input.
- X.TP
- X.B /dev/stdout
- XThe standard output.
- X.TP
- X.B /dev/stderr
- XThe standard error output.
- X.TP
- X.BI /dev/fd/\^ n
- XThe file denoted by the open file descriptor
- X.IR n .
- X.RE
- X.PP
- XThese are particularly useful for error messages. For example:
- X.PP
- X.RS
- X.ft B
- Xprint "You blew it!" > "/dev/stderr"
- X.ft R
- X.RE
- X.PP
- Xwhereas you would otherwise have to use
- X.PP
- X.RS
- X.ft B
- Xprint "You blew it!" | "cat 1>&2"
- X.ft R
- X.RE
- X.PP
- XThese file names may also be used on the command line to name data files.
- X.SS Numeric Functions
- X.PP
- XAWK has the following pre-defined arithmetic functions:
- X.PP
- X.RS
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI atan2( y , " x" )
- Xreturns the arctangent of
- X.I y/x
- Xin radians.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI cos( expr )
- Xreturns the cosine in radians.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI exp( expr )
- Xthe exponential function.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI int( expr )
- Xtruncates to integer.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI log( expr )
- Xthe natural logarithm function.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.B rand()
- Xreturns a random number between 0 and 1.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI sin( expr )
- Xreturns the sine in radians.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI sqrt( expr )
- Xthe square root function.
- X.TP \l'\fBsrand(\fIexpr\fB)\fR'
- X.BI srand( expr )
- Xuse
- X.I expr
- Xas a new seed for the random number generator. If no
- X.I expr
- Xis provided, the time of day will be used.
- XThe return value is the previous seed for the random
- Xnumber generator.
- X.RE
- X.SS String Functions
- X.PP
- XAWK has the following pre-defined string functions:
- X.PP
- X.RS
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X\fBgsub(\fIr\fB, \fIs\fB, \fIt\fB)\fR
- Xfor each substring matching the regular expression
- X.I r
- Xin the string
- X.IR t ,
- Xsubstitute the string
- X.IR s ,
- Xand return the number of substitutions.
- XIf
- X.I t
- Xis not supplied, use
- X.BR $0 .
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X.BI index( s , " t" )
- Xreturns the index of the string
- X.I t
- Xin the string
- X.IR s ,
- Xor 0 if
- X.I t
- Xis not present.
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X.BI length( s )
- Xreturns the length of the string
- X.IR s .
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X.BI match( s , " r" )
- Xreturns the position in
- X.I s
- Xwhere the regular expression
- X.I r
- Xoccurs, or 0 if
- X.I r
- Xis not present, and sets the values of
- X.B RSTART
- Xand
- X.BR RLENGTH .
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X\fBsplit(\fIs\fB, \fIa\fB, \fIr\fB)\fR
- Xsplits the string
- X.I s
- Xinto the array
- X.I a
- Xon the regular expression
- X.IR r ,
- Xand returns the number of fields. If
- X.I r
- Xis omitted,
- X.B FS
- Xis used instead.
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X.BI sprintf( fmt , " expr-list" )
- Xprints
- X.I expr-list
- Xaccording to
- X.IR fmt ,
- Xand returns the resulting string.
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X\fBsub(\fIr\fB, \fIs\fB, \fIt\fB)\fR
- Xthis is just like
- X.BR gsub ,
- Xbut only the first matching substring is replaced.
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X\fBsubstr(\fIs\fB, \fIi\fB, \fIn\fB)\fR
- Xreturns the
- X.IR n -character
- Xsubstring of
- X.I s
- Xstarting at
- X.IR i .
- XIf
- X.I n
- Xis omitted, the rest of
- X.I s
- Xis used.
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X.BI tolower( str )
- Xreturns a copy of the string
- X.IR str ,
- Xwith all the upper-case characters in
- X.I str
- Xtranslated to their corresponding lower-case counterparts.
- XNon-alphabetic characters are left unchanged.
- X.TP \l'\fBsprintf(\fIfmt\fB, \fIexpr-list\fB)\fR'
- X.BI toupper( str )
- Xreturns a copy of the string
- X.IR str ,
- Xwith all the lower-case characters in
- X.I str
- Xtranslated to their corresponding upper-case counterparts.
- XNon-alphabetic characters are left unchanged.
- X.RE
- X.SS String Constants
- X.PP
- XString constants in AWK are sequences of characters enclosed
- Xbetween double quotes (\fB"\fR). Within strings, certain
- X.I "escape sequences"
- Xare recognized, as in C. These are:
- X.PP
- X.RS
- X.TP \l'\fB\e\fIddd\fR'
- X.B \e\e
- XA literal backslash.
- X.TP \l'\fB\e\fIddd\fR'
- X.B \ea
- XThe ``alert'' character; usually the ASCII BEL character.
- X.TP \l'\fB\e\fIddd\fR'
- X.B \eb
- Xbackspace.
- X.TP \l'\fB\e\fIddd\fR'
- X.B \ef
- Xform-feed.
- X.TP \l'\fB\e\fIddd\fR'
- X.B \en
- Xnew line.
- X.TP \l'\fB\e\fIddd\fR'
- X.B \er
- Xcarriage return.
- X.TP \l'\fB\e\fIddd\fR'
- X.B \et
- Xhorizontal tab.
- X.TP \l'\fB\e\fIddd\fR'
- X.B \ev
- Xvertical tab.
- X.TP \l'\fB\e\fIddd\fR'
- X.BI \ex "\^hex digits"
- XThe character represented by the string of hexadecimal digits following
- Xthe
- X.BR \ex .
- XAs in ANSI C, all following hexadecimal digits are considered part of
- Xthe escape sequence.
- X(This feature should tell us something about language design by committee.)
- XE.g., "\ex1B" is the ASCII ESC (escape) character.
- X.TP \l'\fB\e\fIddd\fR'
- X.BI \e ddd
- XThe character represented by the 1-, 2-, or 3-digit sequence of octal
- Xdigits. E.g. "\e033" is the ASCII ESC (escape) character.
- X.TP \l'\fB\e\fIddd\fR'
- X.BI \e c
- XThe literal character
- X.IR c\^ .
- X.RE
- X.PP
- XThe escape sequences may also be used inside constant regular expressions
- X(e.g.,
- X.B "/[\ \et\ef\en\er\ev]/"
- Xmatches whitespace characters).
- X.SH FUNCTIONS
- XFunctions in AWK are defined as follows:
- X.PP
- X.RS
- X\fBfunction \fIname\fB(\fIparameter list\fB) { \fIstatements \fB}\fR
- X.RE
- X.PP
- XFunctions are executed when called from within the action parts of regular
- Xpattern-action statements. Actual parameters supplied in the function
- Xcall are used to instantiate the formal parameters declared in the function.
- XArrays are passed by reference, other variables are passed by value.
- X.PP
- XSince functions were not originally part of the AWK language, the provision
- Xfor local variables is rather clumsy: they are declared as extra parameters
- Xin the parameter list. The convention is to separate local variables from
- Xreal parameters by extra spaces in the parameter list. For example:
- X.PP
- X.RS
- X.ft B
- X.nf
- Xfunction f(p, q, a, b) { # a & b are local
- X ..... }
- X
- X/abc/ { ... ; f(1, 2) ; ... }
- X.fi
- X.ft R
- X.RE
- X.PP
- XThe left parenthesis in a function call is required
- Xto immediately follow the function name,
- Xwithout any intervening white space.
- XThis is to avoid a syntactic ambiguity with the concatenation operator.
- XThis restriction does not apply to the built-in functions listed above.
- X.PP
- XFunctions may call each other and may be recursive.
- XFunction parameters used as local variables are initialized
- Xto the null string and the number zero upon function invocation.
- X.PP
- XThe word
- X.B func
- Xmay be used in place of
- X.BR function .
- X.SH EXAMPLES
- X.nf
- XPrint and sort the login names of all users:
- X
- X.ft B
- X BEGIN { FS = ":" }
- X { print $1 | "sort" }
- X
- X.ft R
- XCount lines in a file:
- X
- X.ft B
- X { nlines++ }
- X END { print nlines }
- X
- X.ft R
- XPrecede each line by its number in the file:
- X
- X.ft B
- X { print FNR, $0 }
- X
- X.ft R
- XConcatenate and line number (a variation on a theme):
- X
- X.ft B
- X { print NR, $0 }
- X.ft R
- X.fi
- X.SH SEE ALSO
- X.IR egrep (1)
- X.PP
- X.IR "The AWK Programming Language" ,
- XAlfred V. Aho, Brian W. Kernighan, Peter J. Weinberger,
- XAddison-Wesley, 1988. ISBN 0-201-07981-X.
- X.PP
- X.IR "The GAWK Manual" ,
- Xpublished by the Free Software Foundation, 1989.
- X.SH SYSTEM V RELEASE 4 COMPATIBILITY
- XA primary goal for
- X.I gawk
- Xis compatibility with the latest version of \s-1UNIX\s+1
- X.IR awk .
- XTo this end,
- X.I gawk
- Xincorporates the following user visible
- Xfeatures which are not described in the AWK book,
- Xbut are part of
- X.I awk
- Xin System V Release 4.
- X.PP
- XThe
- X.B \-v
- Xoption for assigning variables before program execution starts is new.
- XThe book indicates that command line variable assignment happens when
- X.I awk
- Xwould otherwise open the argument as a file, which is after the
- X.B BEGIN
- Xblock is executed. However, in earlier implementations, when such an
- Xassignment appeared before any file names, the assignment would happen
- X.I before
- Xthe
- X.B BEGIN
- Xblock was run. Applications came to depend on this ``feature.''
- XWhen
- X.I awk
- Xwas changed to match its documentation, this option was added to
- Xaccomodate applications that depended upon the old behaviour.
- X.PP
- XWhen processing arguments,
- X.I gawk
- Xuses the special option ``\fB\-\^\-\fP'' to signal the end of
- Xarguments, and warns about, but otherwise ignores, undefined options.
- X.PP
- XThe AWK book does not define the return value of
- X.BR srand() .
- XThe System V Release 4 version of \s-1UNIX\s+1
- X.I awk
- Xhas it return the seed it was using, to allow keeping track
- Xof random number sequences. Therefore
- X.B srand()
- Xin
- X.I gawk
- Xalso returns its current seed.
- X.PP
- XOther new features are:
- XThe use of multiple
- X.B \-f
- Xoptions; the
- X.B ENVIRON
- Xarray; the
- X.BR \ea ,
- Xand
- X.BR \ev ,
- X.B \ex
- Xescape sequences; the
- X.B tolower
- Xand
- X.B toupper
- Xbuilt-in functions; and the ANSI C conversion specifications in
- X.BR printf .
- X.SH GNU EXTENSIONS
- X.I Gawk
- Xhas some extensions to System V
- X.IR awk .
- XThey are described in this section. All the extensions described here
- Xcan be disabled by compiling
- X.I gawk
- Xwith
- X.BR \-DSTRICT ,
- Xor by invoking
- X.I gawk
- Xwith the
- X.B \-c
- Xoption.
- XIf the underlying operating system supports the
- X.B /dev/fd
- Xdirectory and corresponding files, then
- X.I gawk
- Xcan be compiled with
- X.B \-DNO_DEV_FD
- Xto disable the special filename processing.
- X.PP
- XThe following features of
- X.I gawk
- Xare not available in
- XSystem V
- X.IR awk .
- X.RS
- X.TP \l'\(bu'
- X\(bu
- XThe special file names available for I/O redirection are not recognized.
- X.TP \l'\(bu'
- X\(bu
- XThe
- X.B IGNORECASE
- Xvariable and its side-effects are not available.
- X.TP \l'\(bu'
- X\(bu
- XNo path search is performed for files named via the
- X.B \-f
- Xoption. Therefore the
- X.B AWKPATH
- Xenvironment variable is not special.
- X.TP \l'\(bu'
- X\(bu
- XThe
- X.BR \-a ,
- X.BR \-e ,
- X.BR \-c ,
- X.BR \-C ,
- Xand
- X.B \-V
- Xcommand line options.
- X.RE
- X.PP
- XThe AWK book does not define the return value of the
- X.B close
- Xfunction.
- X.IR Gawk\^ 's
- X.B close
- Xreturns the value from
- X.IR fclose (3),
- Xor
- X.IR pclose (3),
- Xwhen closing a file or pipe, respectively.
- X.PP
- XWhen
- X.I gawk
- Xis invoked with the
- X.B \-c
- Xoption,
- Xif the
- X.I fs
- Xargument to the
- X.B \-F
- Xoption is ``t'', then
- X.B FS
- Xwill be set to the tab character.
- XSince this is a rather ugly special case, it is not the default behavior.
- X.ig
- X.PP
- XThe rest of the features described in this section may change at some time in
- Xthe future, or may go away entirely.
- XYou should not write programs that depend upon them.
- X.PP
- X.I Gawk
- Xaccepts the following additional options:
- X.TP
- X.B \-D
- XTurn on general debugging and turn on
- X.IR yacc (1)
- Xor
- X.IR bison (1)
- Xdebugging output during program parsing.
- XThis option should only be of interest to the
- X.I gawk
- Xmaintainers, and may not even be compiled into
- X.IR gawk .
- X.TP
- X.B \-d
- XTurn on general debugging and print the
- X.I gawk
- Xinternal tree as the program is executed.
- XThis option should only be of interest to the
- X.I gawk
- Xmaintainers, and may not even be compiled into
- X.IR gawk .
- X..
- X.SH BUGS
- XThe
- X.B \-F
- Xoption is not necessary given the command line variable assignment feature;
- Xit remains only for backwards compatibility.
- X.PP
- XThere are now too many options.
- XFortunately, most of them are rarely needed.
- X.SH AUTHORS
- XThe original version of \s-1UNIX\s+1
- X.I awk
- Xwas designed and implemented by Alfred Aho,
- XPeter Weinberger, and Brian Kernighan of AT&T Bell Labs. Brian Kernighan
- Xcontinues to maintain and enhance it.
- X.PP
- XPaul Rubin and Jay Fenlason,
- Xof the Free Software Foundation, wrote
- X.IR gawk ,
- Xto be compatible with the original version of
- X.I awk
- Xdistributed in Seventh Edition \s-1UNIX\s+1.
- XJohn Woods contributed a number of bug fixes.
- XDavid Trueman of Dalhousie University, with contributions
- Xfrom Arnold Robbins at Emory University, made
- X.I gawk
- Xcompatible with the new version of \s-1UNIX\s+1
- X.IR awk .
- X.SH ACKNOWLEDGEMENTS
- XBrian Kernighan of Bell Labs
- Xprovided valuable assistance during testing and debugging.
- XWe thank him.
- END_OF_FILE
- if test 33549 -ne `wc -c <'./gawk.1'`; then
- echo shar: \"'./gawk.1'\" unpacked with wrong size!
- fi
- # end of './gawk.1'
- fi
- if test -f './io.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./io.c'\"
- else
- echo shar: Extracting \"'./io.c'\" \(17467 characters\)
- sed "s/^X//" >'./io.c' <<'END_OF_FILE'
- X/*
- X * io.c - routines for dealing with input and output and records
- X */
- X
- X/*
- X * Copyright (C) 1986, 1988, 1989 the Free Software Foundation, Inc.
- X *
- X * This file is part of GAWK, the GNU implementation of the
- X * AWK Progamming Language.
- X *
- X * GAWK is free software; you can redistribute it and/or modify
- X * it under the terms of the GNU General Public License as published by
- X * the Free Software Foundation; either version 1, or (at your option)
- X * any later version.
- X *
- X * GAWK is distributed in the hope that it will be useful,
- X * but WITHOUT ANY WARRANTY; without even the implied warranty of
- X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X * GNU General Public License for more details.
- X *
- X * You should have received a copy of the GNU General Public License
- X * along with GAWK; see the file COPYING. If not, write to
- X * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- X */
- X
- X#include "awk.h"
- X#ifndef O_RDONLY
- X#include <fcntl.h>
- X#endif
- X#include <signal.h>
- X
- Xextern FILE *popen();
- X
- Xstatic void do_file();
- Xstatic IOBUF *nextfile();
- Xstatic int get_a_record();
- Xstatic int iop_close();
- Xstatic IOBUF *iop_alloc();
- Xstatic void close_one();
- Xstatic int close_redir();
- Xstatic IOBUF *gawk_popen();
- Xstatic int gawk_pclose();
- X
- Xstatic struct redirect *red_head = NULL;
- Xstatic int getline_redirect = 0; /* "getline <file" being executed */
- X
- Xextern char *line_buf;
- Xextern int output_is_tty;
- Xextern NODE *ARGC_node;
- Xextern NODE *ARGV_node;
- Xextern NODE **fields_arr;
- X
- Xint field_num;
- X
- Xstatic IOBUF *
- Xnextfile()
- X{
- X static int i = 1;
- X static int files = 0;
- X static IOBUF *curfile = NULL;
- X char *arg;
- X char *cp;
- X int fd = -1;
- X
- X if (curfile != NULL && curfile->cnt != EOF)
- X return curfile;
- X for (; i < (int) (ARGC_node->lnode->numbr); i++) {
- X arg = (*assoc_lookup(ARGV_node, tmp_number((AWKNUM) i)))->stptr;
- X if (*arg == '\0')
- X continue;
- X cp = strchr(arg, '=');
- X if (cp != NULL) {
- X *cp++ = '\0';
- X variable(arg)->var_value = make_string(cp, strlen(cp));
- X *--cp = '='; /* restore original text of ARGV */
- X } else {
- X files++;
- X if (STREQ(arg, "-"))
- X fd = 0;
- X else
- X fd = devopen(arg, "r");
- X if (fd == -1)
- X fatal("cannot open file `%s' for reading (%s)",
- X arg, strerror(errno));
- X /* NOTREACHED */
- X /* This is a kludge. */
- X deref = FILENAME_node->var_value;
- X do_deref();
- X FILENAME_node->var_value =
- X make_string(arg, strlen(arg));
- X FNR_node->var_value->numbr = 0.0;
- X i++;
- X break;
- X }
- X }
- X if (files == 0) {
- X files++;
- X /* no args. -- use stdin */
- X /* FILENAME is init'ed to "-" */
- X /* FNR is init'ed to 0 */
- X fd = 0;
- X }
- X if (fd == -1)
- X return NULL;
- X return curfile = iop_alloc(fd);
- X}
- X
- Xstatic IOBUF *
- Xiop_alloc(fd)
- Xint fd;
- X{
- X IOBUF *iop;
- X struct stat stb;
- X
- X /*
- X * System V doesn't have the file system block size in the
- X * stat structure. So we have to make some sort of reasonable
- X * guess. We use stdio's BUFSIZ, since that is what it was
- X * meant for in the first place.
- X */
- X#ifdef BLKSIZE_MISSING
- X#define DEFBLKSIZE BUFSIZ
- X#else
- X#define DEFBLKSIZE (stb.st_blksize ? stb.st_blksize : BUFSIZ)
- X#endif
- X
- X if (fd == -1)
- X return NULL;
- X emalloc(iop, IOBUF *, sizeof(IOBUF), "nextfile");
- X iop->flag = 0;
- X if (isatty(fd)) {
- X iop->flag |= IOP_IS_TTY;
- X iop->size = BUFSIZ;
- X } else if (fstat(fd, &stb) == -1)
- X fatal("can't stat fd %d (%s)", fd, strerror(errno));
- X else if (lseek(fd, 0L, 0) == -1)
- X iop->size = DEFBLKSIZE;
- X else
- X iop->size = (stb.st_size < DEFBLKSIZE ?
- X stb.st_size+1 : DEFBLKSIZE);
- X errno = 0;
- X iop->fd = fd;
- X emalloc(iop->buf, char *, iop->size, "nextfile");
- X iop->off = iop->buf;
- X iop->cnt = 0;
- X iop->secsiz = iop->size < BUFSIZ ? iop->size : BUFSIZ;
- X emalloc(iop->secbuf, char *, iop->secsiz, "nextfile");
- X return iop;
- X}
- X
- Xvoid
- Xdo_input()
- X{
- X IOBUF *iop;
- X extern int exiting;
- X
- X while ((iop = nextfile()) != NULL) {
- X do_file(iop);
- X if (exiting)
- X break;
- X }
- X}
- X
- Xstatic int
- Xiop_close(iop)
- XIOBUF *iop;
- X{
- X int ret;
- X
- X ret = close(iop->fd);
- X if (ret == -1)
- X warning("close of fd %d failed (%s)", iop->fd, strerror(errno));
- X free(iop->buf);
- X free(iop->secbuf);
- X free((char *)iop);
- X return ret == -1 ? 1 : 0;
- X}
- X
- X/*
- X * This reads in a record from the input file
- X */
- Xstatic int
- Xinrec(iop)
- XIOBUF *iop;
- X{
- X int cnt;
- X int retval = 0;
- X
- X cnt = get_a_record(&line_buf, iop);
- X if (cnt == EOF) {
- X cnt = 0;
- X retval = 1;
- X } else {
- X if (!getline_redirect) {
- X assign_number(&NR_node->var_value,
- X NR_node->var_value->numbr + 1.0);
- X assign_number(&FNR_node->var_value,
- X FNR_node->var_value->numbr + 1.0);
- X }
- X }
- X set_record(line_buf, cnt);
- X
- X return retval;
- X}
- X
- Xstatic void
- Xdo_file(iop)
- XIOBUF *iop;
- X{
- X /* This is where it spends all its time. The infamous MAIN LOOP */
- X if (inrec(iop) == 0)
- X while (interpret(expression_value) && inrec(iop) == 0)
- X ;
- X (void) iop_close(iop);
- X}
- X
- Xint
- Xget_rs()
- X{
- X register NODE *tmp;
- X
- X tmp = force_string(RS_node->var_value);
- X if (tmp->stlen == 0)
- X return 0;
- X return *(tmp->stptr);
- X}
- X
- X/* Redirection for printf and print commands */
- Xstruct redirect *
- Xredirect(tree, errflg)
- XNODE *tree;
- Xint *errflg;
- X{
- X register NODE *tmp;
- X register struct redirect *rp;
- X register char *str;
- X int tflag = 0;
- X int outflag = 0;
- X char *direction = "to";
- X char *mode;
- X int fd;
- X
- X switch (tree->type) {
- X case Node_redirect_append:
- X tflag = RED_APPEND;
- X case Node_redirect_output:
- X outflag = (RED_FILE|RED_WRITE);
- X tflag |= outflag;
- X break;
- X case Node_redirect_pipe:
- X tflag = (RED_PIPE|RED_WRITE);
- X break;
- X case Node_redirect_pipein:
- X tflag = (RED_PIPE|RED_READ);
- X break;
- X case Node_redirect_input:
- X tflag = (RED_FILE|RED_READ);
- X break;
- X default:
- X fatal ("invalid tree type %d in redirect()", tree->type);
- X break;
- X }
- X tmp = force_string(tree_eval(tree->subnode));
- X str = tmp->stptr;
- X for (rp = red_head; rp != NULL; rp = rp->next)
- X if (STREQ(rp->value, str)
- X && ((rp->flag & ~RED_NOBUF) == tflag
- X || (outflag
- X && (rp->flag & (RED_FILE|RED_WRITE)) == outflag)))
- X break;
- X if (rp == NULL) {
- X emalloc(rp, struct redirect *, sizeof(struct redirect),
- X "redirect");
- X emalloc(str, char *, tmp->stlen+1, "redirect");
- X memcpy(str, tmp->stptr, tmp->stlen+1);
- X rp->value = str;
- X rp->flag = tflag;
- X rp->offset = 0;
- X rp->fp = NULL;
- X rp->iop = NULL;
- X /* maintain list in most-recently-used first order */
- X if (red_head)
- X red_head->prev = rp;
- X rp->prev = NULL;
- X rp->next = red_head;
- X red_head = rp;
- X }
- X while (rp->fp == NULL && rp->iop == NULL) {
- X mode = NULL;
- X errno = 0;
- X switch (tree->type) {
- X case Node_redirect_output:
- X mode = "w";
- X break;
- X case Node_redirect_append:
- X mode = "a";
- X break;
- X case Node_redirect_pipe:
- X if ((rp->fp = popen(str, "w")) == NULL)
- X fatal("can't open pipe (\"%s\") for output (%s)",
- X str, strerror(errno));
- X rp->flag |= RED_NOBUF;
- X break;
- X case Node_redirect_pipein:
- X direction = "from";
- X if (gawk_popen(str, rp) == NULL)
- X fatal("can't open pipe (\"%s\") for input (%s)",
- X str, strerror(errno));
- X break;
- X case Node_redirect_input:
- X direction = "from";
- X rp->iop = iop_alloc(devopen(str, "r"));
- X break;
- X default:
- X cant_happen();
- X }
- X if (mode != NULL) {
- X fd = devopen(str, mode);
- X if (fd != -1) {
- X rp->fp = fdopen(fd, mode);
- X if (isatty(fd))
- X rp->flag |= RED_NOBUF;
- X }
- X }
- X if (rp->fp == NULL && rp->iop == NULL) {
- X /* too many files open -- close one and try again */
- X if (errno == ENFILE || errno == EMFILE)
- X close_one();
- X else {
- X /*
- X * Some other reason for failure.
- X *
- X * On redirection of input from a file,
- X * just return an error, so e.g. getline
- X * can return -1. For output to file,
- X * complain. The shell will complain on
- X * a bad command to a pipe.
- X */
- X *errflg = 1;
- X if (tree->type == Node_redirect_output
- X || tree->type == Node_redirect_append)
- X fatal("can't redirect %s `%s' (%s)",
- X direction, str, strerror(errno));
- X else
- X return NULL;
- X }
- X }
- X }
- X if (rp->offset != 0) /* this file was previously open */
- X if (fseek(rp->fp, rp->offset, 0) == -1)
- X fatal("can't seek to %ld on `%s' (%s)",
- X rp->offset, str, strerror(errno));
- X free_temp(tmp);
- X return rp;
- X}
- X
- Xstatic void
- Xclose_one()
- X{
- X register struct redirect *rp;
- X register struct redirect *rplast = NULL;
- X
- X /* go to end of list first, to pick up least recently used entry */
- X for (rp = red_head; rp != NULL; rp = rp->next)
- X rplast = rp;
- X /* now work back up through the list */
- X for (rp = rplast; rp != NULL; rp = rp->prev)
- X if (rp->fp && (rp->flag & RED_FILE)) {
- X rp->offset = ftell(rp->fp);
- X if (fclose(rp->fp))
- X warning("close of \"%s\" failed (%s).",
- X rp->value, strerror(errno));
- X rp->fp = NULL;
- X break;
- X }
- X if (rp == NULL)
- X /* surely this is the only reason ??? */
- X fatal("too many pipes or input files open");
- X}
- X
- XNODE *
- Xdo_close(tree)
- XNODE *tree;
- X{
- X NODE *tmp;
- X register struct redirect *rp;
- X
- X tmp = force_string(tree_eval(tree->subnode));
- X for (rp = red_head; rp != NULL; rp = rp->next) {
- X if (STREQ(rp->value, tmp->stptr))
- X break;
- X }
- X free_temp(tmp);
- X if (rp == NULL) /* no match */
- X return tmp_number((AWKNUM) 0.0);
- X fflush(stdout); /* synchronize regular output */
- X return tmp_number((AWKNUM)close_redir(rp));
- X}
- X
- Xstatic int
- Xclose_redir(rp)
- Xregister struct redirect *rp;
- X{
- X int status = 0;
- X
- X if ((rp->flag & (RED_PIPE|RED_WRITE)) == (RED_PIPE|RED_WRITE))
- X status = pclose(rp->fp);
- X else if (rp->fp)
- X status = fclose(rp->fp);
- X else if (rp->iop) {
- X if (rp->flag & RED_PIPE)
- X status = gawk_pclose(rp);
- X else
- X status = iop_close(rp->iop);
- X
- X }
- X /* SVR4 awk checks and warns about status of close */
- X if (status)
- X warning("failure status (%d) on %s close of \"%s\" (%s).",
- X status,
- X (rp->flag & RED_PIPE) ? "pipe" :
- X "file", rp->value, strerror(errno));
- X if (rp->next)
- X rp->next->prev = rp->prev;
- X if (rp->prev)
- X rp->prev->next = rp->next;
- X else
- X red_head = rp->next;
- X free(rp->value);
- X free((char *)rp);
- X return status;
- X}
- X
- Xint
- Xflush_io ()
- X{
- X register struct redirect *rp;
- X int status = 0;
- X
- X errno = 0;
- X if (fflush(stdout)) {
- X warning("error writing standard output (%s).", strerror(errno));
- X status++;
- X }
- X errno = 0;
- X if (fflush(stderr)) {
- X warning("error writing standard error (%s).", strerror(errno));
- X status++;
- X }
- X for (rp = red_head; rp != NULL; rp = rp->next)
- X /* flush both files and pipes, what the heck */
- X if ((rp->flag & RED_WRITE) && rp->fp != NULL)
- X if (fflush(rp->fp)) {
- X warning("%s flush of \"%s\" failed (%s).",
- X (rp->flag & RED_PIPE) ? "pipe" :
- X "file", rp->value, strerror(errno));
- X status++;
- X }
- X return status;
- X}
- X
- Xint
- Xclose_io ()
- X{
- X register struct redirect *rp;
- X int status = 0;
- X
- X for (rp = red_head; rp != NULL; rp = rp->next)
- X if (close_redir(rp))
- X status++;
- X return status;
- X}
- X
- X/* devopen --- handle /dev/std{in,out,err}, /dev/fd/N, regular files */
- Xint
- Xdevopen (name, mode)
- Xchar *name, *mode;
- X{
- X int openfd = -1;
- X FILE *fdopen ();
- X char *cp;
- X int flag = 0;
- X
- X switch(mode[0]) {
- X case 'r':
- X flag = O_RDONLY;
- X break;
- X
- X case 'w':
- X flag = O_WRONLY|O_CREAT|O_TRUNC;
- X break;
- X
- X case 'a':
- X flag = O_WRONLY|O_APPEND|O_CREAT;
- X break;
- X default:
- X cant_happen();
- X }
- X
- X#if defined(STRICT) || defined(NO_DEV_FD)
- X return (open (name, flag, 0666));
- X#else
- X if (strict)
- X return (open (name, flag, 0666));
- X
- X if (!STREQN (name, "/dev/", 5))
- X return (open (name, flag, 0666));
- X else
- X cp = name + 5;
- X
- X /* XXX - first three tests ignore mode */
- X if (STREQ(cp, "stdin"))
- X return (0);
- X else if (STREQ(cp, "stdout"))
- X return (1);
- X else if (STREQ(cp, "stderr"))
- X return (2);
- X else if (STREQN(cp, "fd/", 3)) {
- X cp += 3;
- X if (sscanf (cp, "%d", & openfd) == 1 && openfd >= 0)
- X /* got something */
- X return openfd;
- X else
- X return -1;
- X } else
- X return (open (name, flag, 0666));
- X#endif
- X}
- X
- X#ifndef MSDOS
- Xstatic IOBUF *
- Xgawk_popen(cmd, rp)
- Xchar *cmd;
- Xstruct redirect *rp;
- X{
- X int p[2];
- X register int pid;
- X
- X rp->pid = -1;
- X rp->iop = NULL;
- X if (pipe(p) < 0)
- X return NULL;
- X if ((pid = fork()) == 0) {
- X close(p[0]);
- X dup2(p[1], 1);
- X close(p[1]);
- X execl("/bin/sh", "sh", "-c", cmd, 0);
- X _exit(127);
- X }
- X if (pid == -1)
- X return NULL;
- X rp->pid = pid;
- X close(p[1]);
- X return (rp->iop = iop_alloc(p[0]));
- X}
- X
- Xstatic int
- Xgawk_pclose(rp)
- Xstruct redirect *rp;
- X{
- X SIGTYPE (*hstat)(), (*istat)(), (*qstat)();
- X int pid;
- X int status;
- X struct redirect *redp;
- X
- X iop_close(rp->iop);
- X if (rp->pid == -1)
- X return rp->status;
- X hstat = signal(SIGHUP, SIG_IGN);
- X istat = signal(SIGINT, SIG_IGN);
- X qstat = signal(SIGQUIT, SIG_IGN);
- X for (;;) {
- X pid = wait(&status);
- X if (pid == -1 && errno == ECHILD)
- X break;
- X else if (pid == rp->pid) {
- X rp->pid = -1;
- X rp->status = status;
- X break;
- X } else {
- X for (redp = red_head; redp != NULL; redp = redp->next)
- X if (pid == redp->pid) {
- X redp->pid = -1;
- X redp->status = status;
- X break;
- X }
- X }
- X }
- X signal(SIGHUP, hstat);
- X signal(SIGINT, istat);
- X signal(SIGQUIT, qstat);
- X return(rp->status);
- X}
- X#else
- Xstatic
- Xstruct {
- X char *command;
- X char *name;
- X} pipes[_NFILE];
- X
- Xstatic IOBUF *
- Xgawk_popen(cmd, rp)
- Xchar *cmd;
- Xstruct redirect *rp;
- X{
- X extern char *strdup(const char *);
- X int current;
- X char *name;
- X static char cmdbuf[256];
- X
- X /* get a name to use. */
- X if ((name = tempnam(".", "pip")) == NULL)
- X return NULL;
- X sprintf(cmdbuf,"%s > %s", cmd, name);
- X system(cmdbuf);
- X if ((current = open(name,O_RDONLY)) == -1)
- X return NULL;
- X pipes[current].name = name;
- X pipes[current].command = strdup(cmd);
- X return (rp->iop = iop_alloc(current));
- X}
- X
- Xstatic int
- Xgawk_pclose(rp)
- Xstruct redirect *rp;
- X{
- X int cur = rp->iop->fd;
- X int rval;
- X
- X rval = iop_close(rp->iop);
- X
- X /* check for an open file */
- X if (pipes[cur].name == NULL)
- X return -1;
- X unlink(pipes[cur].name);
- X free(pipes[cur].name);
- X pipes[cur].name = NULL;
- X free(pipes[cur].command);
- X return rval;
- X}
- X#endif
- X
- X#define DO_END_OF_BUF len = bp - iop->off;\
- X used = last - start;\
- X while (len + used > iop->secsiz) {\
- X iop->secsiz *= 2;\
- X erealloc(iop->secbuf,char *,iop->secsiz,"get");\
- X }\
- X last = iop->secbuf + used;\
- X start = iop->secbuf;\
- X memcpy(last, iop->off, len);\
- X last += len;\
- X iop->cnt = read(iop->fd, iop->buf, iop->size);\
- X if (iop->cnt < 0)\
- X return iop->cnt;\
- X end_data = iop->buf + iop->cnt;\
- X iop->off = bp = iop->buf;
- X
- X#define DO_END_OF_DATA iop->cnt = read(iop->fd, end_data, end_buf - end_data);\
- X if (iop->cnt < 0)\
- X return iop->cnt;\
- X end_data += iop->cnt;\
- X if (iop->cnt == 0)\
- X break;\
- X iop->cnt = end_data - iop->buf;
- X
- Xstatic int
- Xget_a_record(res, iop)
- Xchar **res;
- XIOBUF *iop;
- X{
- X register char *end_data;
- X register char *end_buf;
- X char *start;
- X register char *bp;
- X register char *last;
- X int len, used;
- X register char rs = get_rs();
- X
- X if (iop->cnt < 0)
- X return iop->cnt;
- X if ((iop->flag & IOP_IS_TTY) && output_is_tty)
- X fflush(stdout);
- X end_data = iop->buf + iop->cnt;
- X if (iop->off >= end_data) {
- X iop->cnt = read(iop->fd, iop->buf, iop->size);
- X if (iop->cnt <= 0)
- X return iop->cnt = EOF;
- X end_data = iop->buf + iop->cnt;
- X iop->off = iop->buf;
- X }
- X last = start = bp = iop->off;
- X end_buf = iop->buf + iop->size;
- X if (rs == 0) {
- X while (!(*bp == '\n' && bp != iop->buf && bp[-1] == '\n')) {
- X if (++bp == end_buf) {
- X DO_END_OF_BUF
- X }
- X if (bp == end_data) {
- X DO_END_OF_DATA
- X }
- X }
- X if (*bp == '\n' && bp != iop->off && bp[-1] == '\n') {
- X int tmp = 0;
- X
- X /* allow for more than two newlines */
- X while (*bp == '\n') {
- X tmp++;
- X if (++bp == end_buf) {
- X DO_END_OF_BUF
- X }
- X if (bp == end_data) {
- X DO_END_OF_DATA
- X }
- X }
- X iop->off = bp;
- X bp -= 1 + tmp;
- X } else if (bp != iop->buf && bp[-1] != '\n') {
- X warning("record not terminated");
- X iop->off = bp + 2;
- X } else {
- X bp--;
- X iop->off = bp + 2;
- X }
- X } else {
- X while (*bp++ != rs) {
- X if (bp == end_buf) {
- X DO_END_OF_BUF
- X }
- X if (bp == end_data) {
- X DO_END_OF_DATA
- X }
- X }
- X if (*--bp != rs) {
- X warning("record not terminated");
- X bp++;
- X }
- X iop->off = bp + 1;
- X }
- X if (start == iop->secbuf) {
- X len = bp - iop->buf;
- X if (len > 0) {
- X used = last - start;
- X while (len + used > iop->secsiz) {
- X iop->secsiz *= 2;
- X erealloc(iop->secbuf,char *,iop->secsiz,"get2");
- X }
- X last = iop->secbuf + used;
- X start = iop->secbuf;
- X memcpy(last, iop->buf, len);
- X last += len;
- X }
- X } else
- X last = bp;
- X *last = '\0';
- X *res = start;
- X return last - start;
- X}
- X
- XNODE *
- Xdo_getline(tree)
- XNODE *tree;
- X{
- X struct redirect *rp;
- X IOBUF *iop;
- X int cnt;
- X NODE **lhs;
- X int redir_error = 0;
- X
- X if (tree->rnode == NULL) { /* no redirection */
- X iop = nextfile();
- X if (iop == NULL) /* end of input */
- X return tmp_number((AWKNUM) 0.0);
- X } else {
- X rp = redirect(tree->rnode, &redir_error);
- X if (rp == NULL && redir_error) /* failed redirect */
- X return tmp_number((AWKNUM) -1.0);
- X iop = rp->iop;
- X getline_redirect++;
- X }
- X if (tree->lnode == NULL) { /* no optional var. -- read in $0 */
- X if (inrec(iop) != 0) {
- X getline_redirect = 0;
- X return tmp_number((AWKNUM) 0.0);
- X }
- X } else { /* read in a named variable */
- X char *s = NULL;
- X
- X lhs = get_lhs(tree->lnode, 1);
- X cnt = get_a_record(&s, iop);
- X if (!getline_redirect) {
- X assign_number(&NR_node->var_value,
- X NR_node->var_value->numbr + 1.0);
- X assign_number(&FNR_node->var_value,
- X FNR_node->var_value->numbr + 1.0);
- X }
- X if (cnt == EOF) {
- X getline_redirect = 0;
- X free(s);
- X return tmp_number((AWKNUM) 0.0);
- X }
- X *lhs = make_string(s, strlen(s));
- X do_deref();
- X /* we may have to regenerate $0 here! */
- X if (field_num == 0)
- X set_record(fields_arr[0]->stptr, fields_arr[0]->stlen);
- X field_num = -1;
- X }
- X getline_redirect = 0;
- X return tmp_number((AWKNUM) 1.0);
- X}
- END_OF_FILE
- if test 17467 -ne `wc -c <'./io.c'`; then
- echo shar: \"'./io.c'\" unpacked with wrong size!
- fi
- # end of './io.c'
- fi
- if test -f './missing.d/memcpy.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./missing.d/memcpy.c'\"
- else
- echo shar: Extracting \"'./missing.d/memcpy.c'\" \(261 characters\)
- sed "s/^X//" >'./missing.d/memcpy.c' <<'END_OF_FILE'
- X/*
- X * memcpy --- copy strings.
- X *
- X * We supply this routine for those systems that aren't standard yet.
- X */
- X
- Xchar *
- Xmemcpy (dest, src, l)
- Xregister char *dest, *src;
- Xregister int l;
- X{
- X register char *ret = dest;
- X
- X while (l--)
- X *dest++ = *src++;
- X
- X return ret;
- X}
- END_OF_FILE
- if test 261 -ne `wc -c <'./missing.d/memcpy.c'`; then
- echo shar: \"'./missing.d/memcpy.c'\" unpacked with wrong size!
- fi
- # end of './missing.d/memcpy.c'
- fi
- echo shar: End of archive 11 \(of 16\).
- cp /dev/null ark11isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-